//火麒麟翻牌机算法
module.exports = function() {
  var CARD_RAGGED              = 1     //散牌
  var CARD_7OFBETTER           = 2     //7以上的一对
  var CARD_2PAIR               = 3     //两对
  var CARD_3OFAKING            = 4     //三条
  var CARD_STRAIGHT            = 5     //顺子
  var CARD_FLUSH               = 6     //同花
  var CARD_FULLHOUSE           = 7     //葫芦
  var CARD_LITTLE_4OFAKIND     = 8     //小四条
  var CARD_BIG_4OFAKIND        = 9     //大四条
  var CARD_STRFLUSH            = 10    //同花顺
  var CARD_5OFAKING            = 11    //五条
  var CARD_ROYALFLUSH          = 12    //同花大顺
  var CARD_FIVE_BARS           = 13    //五鬼
  
  var oddsList = {
    "1" : 0,
    "2" : 1,
    "3" : 2,
    "4" : 3,
    "5" : 5,
    "6" : 7,
    "7" : 10,
    "8" : 50,
    "9" : 80,
    "10" : 120,
    "11" : 250,
    "12" : 500,
    "13" : 1000
  }
  var card_weight = [0,14,2,3,4,5,6,7,8,9,10,11,12,13,20]
  this.cards = []                  //初始牌库
  this.handCards = []              //玩家手牌
  this.availableCards = []         //剩余可用牌组

  /**
   * 获取牌型
   * @Author   wfd
   * @DateTime 2018-10-08
  */
  this.getCardType = function(handCards) {
    // console.log("火麒麟")
    if(!handCards || typeof(handCards) != "object" || handCards.length != 5){
      return false
    }
    var tmpHand = []
    for(var i = 0;i < handCards.length;i++){
      tmpHand[i] = {}
      for(var j in handCards[i]){
        tmpHand[i][j] = handCards[i][j]
      }
    }
    //从小到大排序
    tmpHand.sort(function(a,b) { 
      if(card_weight[a.num] > card_weight[b.num] || (card_weight[a.num] == card_weight[b.num] && a.type > b.type)){
        return 1
      }else{
        return -1
      }
    })
    // console.log("tmpHand",tmpHand)
    var nums = []
    for(var i = 0;i <= 14;i++){
      nums[i] = 0
    }
    var maxCount = 0            //除鬼以外最大同点牌数
    var secondCount = 0         //除鬼以外第二大同点牌数
    var maxPoint = 0            //除鬼以外最大同点点数
    var maxNum = 0              //除鬼以外最大点数
    var minNum = tmpHand[0].num //除鬼以外最小点数
    var guiCount = 0            //鬼牌数量
    var tonghuaFlag = true      //同花标识
    var shunziFlag = false      //顺子标识
    for(var i = 0;i < tmpHand.length;i++){
      var num = tmpHand[i].num
      nums[num]++
    }
    guiCount = nums[14]
    for(var i = 0;i < nums.length;i++){
      if(nums[i] && i < 14){
        if(card_weight[i] > card_weight[maxNum]){
          maxNum = i
        }
        // console.log("==",i,maxPoint,i > maxPoint)
        if(nums[i] > maxCount || (nums[i] == maxCount && card_weight[i] > card_weight[maxPoint])){
          maxCount = nums[i]
          maxPoint = i
        }
      }
    }
    //第二大同点数
    for(var i in nums){
      if(nums[i] && i < 14 && i != maxPoint){
        if(nums[i] > secondCount){
          secondCount = nums[i]
        }
      }
    }
    // console.log("nums",nums,maxCount,maxPoint,secondCount,guiCount)
    for(var i = 1;i < tmpHand.length;i++){
      if(tmpHand[i].num < 14){
        if(tmpHand[i].type != tmpHand[i-1].type){
          tonghuaFlag = false
          break
        }
      }
    }
    if(maxCount == 1 && (card_weight[maxNum] - card_weight[minNum] <= 4 || nums[1] + nums[2] + nums[3] + nums[4] + nums[5] + nums[14] == 5)){
      // console.log("shunziFlag",shunziFlag,card_weight[maxNum] - card_weight[minNum],maxNum,minNum)
      shunziFlag = true
    }
    var info ={
      type : CARD_RAGGED,
      price : 0
    }
    //同花大顺
    if(tonghuaFlag && shunziFlag && card_weight[minNum] >= 10){
      info.type = CARD_ROYALFLUSH
      info.price = oddsList[info.type]
      return info
    }
    //五条
    if(maxCount + guiCount >= 5){
      info.type = CARD_5OFAKING
      info.price = oddsList[info.type]
      return info
    }
    //同花顺
    if(tonghuaFlag && shunziFlag){
      info.type = CARD_STRFLUSH
      info.price = oddsList[info.type]
      return info
    }
    //四条
    if(maxCount + guiCount >= 4){
      if(card_weight[maxPoint] >= 11){
        //大四条
        info.type = CARD_BIG_4OFAKIND
      }else{
        //小四条
        info.type = CARD_LITTLE_4OFAKIND
      }
      info.price = oddsList[info.type]
      return info
    }
    //葫芦
    if(maxCount + secondCount + guiCount >= 5){
      info.type = CARD_FULLHOUSE
      info.price = oddsList[info.type]
      return info
    }
    //同花
    if(tonghuaFlag){
      info.type = CARD_FLUSH
      info.price = oddsList[info.type]
      return info
    }
    //顺子
    if(shunziFlag){
      info.type = CARD_STRAIGHT
      info.price = oddsList[info.type]
      return info
    }
    //三条
    if(maxCount + guiCount >= 3){
      info.type = CARD_3OFAKING
      info.price = oddsList[info.type]
      return info
    }
    //两对
    if(maxCount + secondCount + guiCount >= 4){
      info.type = CARD_2PAIR
      info.price = oddsList[info.type]
      return info
    }
    //7以上一对
    if(maxCount + guiCount >= 2 && card_weight[maxPoint] >= 7){
      info.type = CARD_7OFBETTER
      info.price = oddsList[info.type]
      return info
    }
    //散牌
    info.type = CARD_RAGGED
    info.price = oddsList[info.type]
    return info
  }
  /**
   * 快速获取牌型
   * @Author   wfd
   * @DateTime 2018-10-08
   */
   // this.getCardTypeQuickly = function(handCards) {
   //    if(!handCards || typeof(handCards) != "object" || handCards.length != 5){
   //      return false
   //    }
   //    var str = ""
   //    for(var i = 0;i < handCards.length;i++){
   //      str += handCards[i].index
   //    }
   //    var info ={
   //      type : CARD_RAGGED,
   //      price : 0
   //    }
   //    if(flopCardCfg[str]){
   //      info.type = flopCardCfg[str]
   //      info.price = oddsList[info.type]
   //    }else{
   //      console.log("error: ",str)
   //    }
   //    return info
   // }
  /**
   * 洗牌
   * @Author   wfd
   * @DateTime 2018-10-08
  */
  this.shuffle = function() {
    this.cards = []
    this.handCards = []
    var count = 0
    for(var i = 1;i <= 13;i++){
      for(var j = 0;j < 4;j++){
        this.cards.push({num : i,type : j,index : count++})
      }
    }
    this.cards.push({num : 14,type : 0,index : count++})
    this.cards.push({num : 14,type : 1,index : count++})
    //洗牌
    // for(var i = 0;i < this.cards.length;i++){
    //   var tmpIndex = Math.floor(Math.random() * this.cards.length)
    //   var tmpCard = this.cards[i]
    //   this.cards[i] = this.cards[tmpIndex]
    //   this.cards[tmpIndex] = tmpCard
    // }
  }
  /**
   * 发牌
   * @Author   wfd
   * @DateTime 2018-10-08
  */
  this.sendCard = function(control,inventory,bet,count) {
    // console.log("sendCard",control)
    this.availableCards = []
    this.handCards = []
    for(var i = 0;i < this.cards.length;i++){
      this.availableCards[i] = i
    }
    for(var i = 0;i < 5;i++){
      var rand = Math.floor(Math.random() * this.availableCards.length)
      var index = this.availableCards.splice(rand,1)[0]
      this.handCards.push(this.cards[index])
    }
    if(typeof(count) != "number" || count > 30){
      return
    }
    var result = this.getCardType(this.handCards)
    // console.log(count,result)
    if(inventory !== false && result.price > 0 && inventory < result.price * bet){
      // console.log("强制库存控制 : ",inventory,result,result.price * bet,result.price > 0)
      this.sendCard(-1,inventory,bet,++count)
    }else{
      if(control > 0){
        //概率换好牌,重新发牌
        if(Math.random() < control && result.type < 3){
          this.sendCard(1,inventory,bet,++count)
        }
      }else{
        //概率换差牌
        if(Math.random() < -control && result.type > 1){
          this.sendCard(-1,inventory,bet,++count)
        }
      }
    }
  }
  /**
   * 换牌
   * @Author   wfd
   * @DateTime 2018-10-08
  */
  this.changeCards = function(indexs,control,count) {
    var flag = false
    if(Math.random() < -control){
      flag = true
    }
    var minType = false
    var minIndex = 0
    var minTmpAvailableCards = []
    var minHandCards = []
    while(count < 30){
      count++
      var tmpAvailableCards = []
      for(var i = 0;i < this.availableCards.length;i++){
        tmpAvailableCards[i] = this.availableCards[i]
      }
      //换牌
      for(var i = 0;i < indexs.length;i++){
        var rand = Math.floor(Math.random() * tmpAvailableCards.length)
        var index = tmpAvailableCards.splice(rand,1)[0]
        this.handCards[indexs[i]] = this.cards[index]
      }
      var result = this.getCardType(this.handCards)
      console.log(count,result)
      if(!minType || result.type < minType){
        console.log("change",this.handCards)
        minIndex = count
        minType = result.type
        minTmpAvailableCards = tmpAvailableCards
        for(var i = 0;i < this.handCards.length;i++){
          minHandCards[i] = this.handCards[i]
        }
      }
      if(result.type <= 1){
        flag = false
      }
      if(!flag){
        break
      }
    }
    console.log("count",count,minIndex)
    this.availableCards = tmpAvailableCards
    this.handCards = minHandCards
  }
  /**
   * 保留牌
   * @Author   wfd
   * @DateTime 2018-10-22
  */
  this.holdCards = function(handCards) {
    // console.log(handCards)
    var tmpHand = []
    var cards = []
    for(var i = 0;i < handCards.length;i++){
      tmpHand[i] = {}
      for(var j in handCards[i]){
        tmpHand[i][j] = handCards[i][j]
      }
    }
    //从小到大排序
    tmpHand.sort(function(a,b) { 
      if(card_weight[a.num] > card_weight[b.num] || (card_weight[a.num] == card_weight[b.num] && a.type > b.type)){
        return 1
      }else{
        return -1
      }
    })
    // console.log("tmpHand",tmpHand)
    var nums = []
    for(var i = 0;i <= 14;i++){
      nums[i] = 0
    }
    for(var i = 0;i < tmpHand.length;i++){
      var num = tmpHand[i].num
      nums[num]++
    }
    var types = []
    for(var i = 0;i <= 3;i++){
      types[i] = 0
    }
    for(var i = 0;i < tmpHand.length;i++){
      if(tmpHand[i].num != 14){
        var type = tmpHand[i].type
        types[type]++
      }
    }
    //保留除鬼以外两张以上同点数牌
    for(var i = 0;i < handCards.length;i++){
      if(handCards[i].num != 14 && nums[handCards[i].num] >= 2){
        cards.push(handCards[i])
      }
    }
    // console.log("111",cards,types,nums)
    var maxLength = 0
    //若无对子以上牌，判断顺子或同花
    if(cards.length + nums[14] < 2 || (cards.length + nums[14] == 2 && cards.length && card_weight[cards[0].num] < 7)){
      //先判断同花
      for(var i = 0;i < types.length;i++){
        if(types[i] + nums[14] >= 4){
          var tmpLength = 0
          var tmpHandCards = []
          for(var j = 0;j < handCards.length;j++){
            if(handCards[j].num != 14 && handCards[j].type == i){
              tmpLength++
              tmpHandCards.push(handCards[j])
            }
          }
          if(tmpLength > maxLength){
            maxLength = tmpLength
            cards = tmpHandCards
          }
        }
      }
      if(cards.length + nums[14] < 5){
        //再判断顺子
        for(var i = 14;i >= 4;i--){
          var tmpi = i
          if(tmpi == 14){
            tmpi = 1
          }
          if(nums[tmpi]){
            var tmpCont = 0
            var tmpList = {}
            for(var j = 0;j < 5;j++){
              var tmpIndex = i - j
              if(tmpIndex == 14){
                tmpIndex = 1
              }
              if(nums[tmpIndex] > 0){
                tmpCont++
                tmpList[tmpIndex] = true
              }
            }
            // console.log(tmpCont,tmpList)
            if(tmpCont > cards.length && tmpCont + nums[14] >= 4){
              var tmpHandCards = []
              for(var j = 0;j < tmpHand.length;j++){
                if(tmpList[tmpHand[j].num]){
                  tmpHandCards.push(tmpHand[j])
                  delete tmpList[tmpHand[j].num]
                }
              }
              cards = tmpHandCards
              break
            }
          }
        }
      }
    }
    // console.log("333",cards)
    //保留鬼牌
    for(var i = 0;i < handCards.length;i++){
      if(handCards[i].num == 14){
        cards.push(handCards[i])
      }
    }
    // console.log(JSON.stringify(cards))
    // console.log(cards)
    return cards
  }
  /**
   * 保留牌类型
   * @Author   wfd
   * @DateTime 2018-11-26
  */
  this.holdCardsType = function(holdCards) {
    var tonghuaFlag = false
    var shunziFlag = false
    var nums = []
    var maxNumLength = 0
    var types = []
    var tmpHand = []
    for(var i = 0;i < holdCards.length;i++){
      tmpHand[i] = {}
      for(var j in holdCards[i]){
        tmpHand[i][j] = holdCards[i][j]
      }
    }
    for(var i = 0;i <= 14;i++){
      nums[i] = 0
    }
    for(var i = 0;i <= 3;i++){
      types[i] = 0
    }
    for(var i = 0;i < tmpHand.length;i++){
      var num = tmpHand[i].num
      nums[num]++
      if(tmpHand[i].num != 14){
        var type = tmpHand[i].type
        types[type]++
        if(nums[num] > maxNumLength){
          maxNumLength = nums[num]
        }
      }
    }
    //从小到大排序
    tmpHand.sort(function(a,b) { 
      if(card_weight[a.num] > card_weight[b.num] || (card_weight[a.num] == card_weight[b.num] && a.type > b.type)){
        return 1
      }else{
        return -1
      }
    })
    //双王特殊处理
    if(holdCards.length == 2 && holdCards[0].num == holdCards[1].num && holdCards[0].num == 14){
      return true
    }
    //三条、四条、五条特殊处理
    if(maxNumLength + nums[14] == holdCards.length && holdCards.length >= 3){
      return true
    }
    if(!holdCards || holdCards.length < 4){
      return false
    }
    //先判断同花
    for(var i = 0;i <= types.length;i++){
      if(types[i] + nums[14] >= tmpHand.length){
        tonghuaFlag = true
        break
      }
    }
    //再判断顺子    除王外数量为1  且相距5以内
    var singleFlag = true
    var maxIndex = tmpHand.length - 1
    for(var i = 1;i < tmpHand.length;i++){
      if(tmpHand[i].num == 14){
        maxIndex = i - 1
        break
      }else if(nums[tmpHand[i].num] != 1){
        singleFlag = false
        break
      }
    }
    if(singleFlag && tmpHand[maxIndex]){
      if(card_weight[tmpHand[maxIndex].num] - card_weight[tmpHand[0].num] < 5){
        shunziFlag = true
      }else if(tmpHand[maxIndex].num == 1 && tmpHand[0].num >= 10){
        shunziFlag = true
      }
    }
    //同花顺返回true
    if(shunziFlag && tonghuaFlag){
      return true
    }else{
      return false
    }
  }
}